﻿using System;

namespace CarPCBATest.Procedure
{
    internal class CRCGeneration
    {
        private static byte[] crcTable = new byte[256];

        static CRCGeneration()
        {
            GenerateCRCTable();
        }

        public static byte ComputeChecksum(byte[] data, int startIndex, int endIndex)
        {
            byte crc = 0xff;
            for (int i = startIndex; i <= endIndex; i++)
            {
                crc = crcTable[crc ^ data[i]];
            }

            //we have to reverse the final remainder to get the CRC value, for example, if
            //final remainder = 0010 1100, we need to reverse it to 0011 0100
            crc = (byte)(((crc & 0x80) >> 7) + ((crc & 0x40) >> 5) + ((crc & 0x20) >> 3) + ((crc & 0x10) >> 1) + ((crc & 0x08) << 1)
                + ((crc & 0x04) << 3) + ((crc & 0x02) << 5) + ((crc & 0x01) << 7));
            Console.WriteLine(crc.ToString("X16"));
            return crc;
        }

        private static void GenerateCRCTable()
        {
            byte lsb = 0x01;    //LSB
            byte polynomial = 0x8C; //多项式
            for (int i = 0; i < 256; ++i)
            {
                byte crc = (byte)i;

                for (int j = 8; j > 0; j--)
                {
                    crc = (byte)((crc & lsb) != 0 ? ((crc >> 1) ^ polynomial) : crc >> 1);
                }

                crcTable[i] = crc;
            }
        }
    }
}